package com.dbflow5.database;

import com.dbflow5.config.DBFlowDatabase;
import com.dbflow5.config.DatabaseConfig;
import ohos.app.Context;
import ohos.data.DatabaseHelper;
import ohos.data.rdb.RdbOpenCallback;
import ohos.data.rdb.RdbStore;
import ohos.data.rdb.StoreConfig;

/**
 * Description: Wraps around the [SQLiteOpenHelper] and provides extra features for use in this library.
 */
public class OhosSQLiteOpenHelper extends DatabaseHelper implements OpenHelper, OpenHelperDelegate /*by databaseHelperDelegate*/ {

    DBFlowDatabase dbFlowDatabase;
    DatabaseCallback listener;
    private final LocalDatabaseHelperDelegate databaseHelperDelegate;

    private OhosDatabase ohosDatabase = null;
    private final String _databaseName;

    public OhosSQLiteOpenHelper(Context context, DBFlowDatabase dbFlowDatabase, DatabaseCallback listener) {
        super(context);
        this.dbFlowDatabase = dbFlowDatabase;
        this.listener = listener;
        _databaseName = dbFlowDatabase.getDatabaseFileName();

        OpenHelper openHelper = null;
        if(dbFlowDatabase.backupEnabled()){
            // Temp database mirrors existing
            openHelper = new BackupHelper(context, LocalDatabaseHelperDelegate.getTempDbFileName(dbFlowDatabase), dbFlowDatabase.databaseVersion(), dbFlowDatabase);
        }
        databaseHelperDelegate = new LocalDatabaseHelperDelegate(context, listener, dbFlowDatabase, openHelper);
    }

    @Override
    public DatabaseWrapper database(){
        if (ohosDatabase == null || !ohosDatabase.database.isOpen()) {
            StoreConfig config = StoreConfig.newDefaultConfig(dbFlowDatabase.getDatabaseFileName());
            RdbOpenCallback callback = new RdbOpenCallback() {
                @Override
                public void onCreate(RdbStore store) {
                    databaseHelperDelegate.onCreate(OhosDatabase.from(store));
                }

                @Override
                public void onOpen(RdbStore store) {
                    databaseHelperDelegate.onOpen(OhosDatabase.from(store));
                }

                @Override
                public void onUpgrade(RdbStore store, int oldVersion, int newVersion) {
                    databaseHelperDelegate.onUpgrade(OhosDatabase.from(store), oldVersion, newVersion);
                }

                @Override
                public void onDowngrade(RdbStore store, int currentVersion, int targetVersion) {
                    databaseHelperDelegate.onDowngrade(OhosDatabase.from(store), currentVersion, targetVersion);
                }
            };
            ohosDatabase = OhosDatabase.from(getRdbStore(config, dbFlowDatabase.databaseVersion(), callback));
        }
        return ohosDatabase;
    }

    @Override
    public void setWriteAheadLoggingEnabled(boolean enabled) {
    }

    @Override
    public void setDatabaseListener(DatabaseCallback callback) {
        databaseHelperDelegate.setDatabaseHelperListener(callback);
    }

    @Override
    public void closeDB() {
        if(ohosDatabase != null && ohosDatabase.database != null) {
            ohosDatabase.database.close();
        }
    }

    @Override
    public void deleteDB() {
        deleteRdbStore(_databaseName);
    }

    @Override
    public LocalDatabaseHelperDelegate delegate() {
        return null;
    }

    @Override
    public boolean isDatabaseIntegrityOk() {
        return false;
    }

    @Override
    public void performRestoreFromBackup() {
        databaseHelperDelegate.performRestoreFromBackup();
    }

    @Override
    public void backupDB() {
        databaseHelperDelegate.backupDB();
    }

    /**
     * Simple helper to manage backup.
     */
    private static class BackupHelper extends DatabaseHelper implements OpenHelper {
        //context, name, null, version
        Context context;
        String name;
        int version;
        DBFlowDatabase databaseDefinition;

        private OhosDatabase ohosDatabase = null;
        private final LocalDatabaseHelper databaseHelper;
        private final String _databaseName;

        BackupHelper(Context context, String name, int version, DBFlowDatabase databaseDefinition){
            super(context);
            this.context = context;
            this.name = name;
            this.version = version;
            this.databaseDefinition = databaseDefinition;
            this.databaseHelper = new LocalDatabaseHelper(new OhosMigrationFileHelper(context), databaseDefinition);
            this._databaseName = databaseDefinition.getDatabaseFileName();
        }

        @Override
        public void setWriteAheadLoggingEnabled(boolean enabled) {
        }

        @Override
        public void setDatabaseListener(DatabaseCallback callback) {
        }

        @Override
        public void closeDB() {

        }

        @Override
        public void deleteDB() {
            deleteRdbStore(_databaseName);
        }

        @Override
        public DatabaseWrapper database() {
            if (ohosDatabase == null) {
                StoreConfig config = StoreConfig.newDefaultConfig(name);
                RdbOpenCallback callback = new RdbOpenCallback() {
                    @Override
                    public void onCreate(RdbStore store) {
                        databaseHelper.onCreate(OhosDatabase.from(store));
                    }

                    @Override
                    public void onOpen(RdbStore store) {
                        databaseHelper.onOpen(OhosDatabase.from(store));
                    }

                    @Override
                    public void onUpgrade(RdbStore store, int oldVersion, int newVersion) {
                        databaseHelper.onUpgrade(OhosDatabase.from(store), oldVersion, newVersion);
                    }

                    @Override
                    public void onDowngrade(RdbStore store, int currentVersion, int targetVersion) {
                        databaseHelper.onDowngrade(OhosDatabase.from(store), currentVersion, targetVersion);
                    }
                };
                ohosDatabase = OhosDatabase.from(getRdbStore(config, version, callback));
            }
            return ohosDatabase;
        }

        @Override
        public LocalDatabaseHelperDelegate delegate() {
            return null;
        }

        @Override
        public boolean isDatabaseIntegrityOk() {
            return false;
        }

        @Override
        public void performRestoreFromBackup() {
        }

        @Override
        public void backupDB() {

        }
    }

    public static DatabaseConfig.OpenHelperCreator createHelperCreator(Context context) {
        return (db, callback) -> new OhosSQLiteOpenHelper(context, db, callback);
    }
}

